#include "spi.h"

/*
作用:初始化SPI2和GPIO
参数:无
返回值:无
*/
void SPI2_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    SPI_InitTypeDef SPI_InitStructure;

    RCC_APB2PeriphClockCmd(SPI_GPIO_CLK, ENABLE); // 使能GPIOB时钟
    SPI_APBxClock_FUN(SPI_CLK, ENABLE);           // 使能SPI2时钟

    // 配置GPIO
    GPIO_InitStructure.GPIO_Pin = SPI_GPIO_SCK_PIN | SPI_GPIO_MISO_PIN | SPI_GPIO_MOSI_PIN; // 选择SPI2的SCK,MISO,MOSI引脚
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;                                         // 选择引脚工作在推挽复用输出模式
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                                       // 设置引脚速率为50MHz
    GPIO_Init(GPIOB, &GPIO_InitStructure);                                                  // 根据GPIO_InitStructure中定义的结构体初始化GPIOB

    GPIO_SetBits(SPI_GPIO_SCK_PORT, SPI_GPIO_SCK_PIN | SPI_GPIO_MISO_PIN | SPI_GPIO_MOSI_PIN); // 上拉SPI引脚

    // 配置SPI属性
    SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;   // 设置SPI全双工双线模式
    SPI_InitStructure.SPI_Mode = SPI_Mode_Master;                        // 设置SPI工作模式为主模式
    SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;                    // 设置数据大小为8位
    SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;                          // 空闲状态时SCK脚高电平
    SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;                         // 第2个跳变沿数据采样
    SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;                            // NSS信号由软件控制
    SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256; // 设置波特率预分频值为256
    SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;                   // 数据传输从MSB位开始
    SPI_InitStructure.SPI_CRCPolynomial = 7;                             // CRC值计算的多项式
    SPI_Init(SPIx, &SPI_InitStructure);                                  // 根据SPI_InitStructure初始化SPI2

    SPI_Cmd(SPIx, ENABLE); // 使能SPI2
}

/*
作用:SPI2发送并接受一个字节
参数data:内容
返回值:SPI2接受的一个字节的数据
*/
uint8_t SPI2_ReadWriteByte(uint8_t data)
{
    u8 SPItimeout = 0;

    // 检查并等待至TX缓冲区为空
    while (SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_TXE) == RESET)
    {
        SPItimeout++;
        if (SPItimeout > 200)
        {
            return 0;
        }
    }

    // 程序执行到此处,TX缓冲区已空,通过SPIx外设发送一个数据
    SPI_I2S_SendData(SPIx, data);
    SPItimeout = 0;

    // 检查并等待至RX缓冲区为空
    while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET)
    {
        SPItimeout++;
        if (SPItimeout > 200)
        {
            return 0;
        }
    }

    // 程序执行到此处，说明数据发送完毕，并接收到一个字节，并返回一个字节的数据
    return SPI_I2S_ReceiveData(SPIx);
}
